package easier.kotlin

fun main() {

    val suc = Result.Success("success")
    val failed = Result.Failed("failed")
    val ex = Result.Exception

    object : TestT<Int, String> {
        override fun map(e: Int): String {
            return e.toString()
        }
    }
}

/**
 * 函数定义
 */
fun sum(a: Int, b: Int): Int {
    return a + b
}

/**
 * 表达式作为函数体，返回类型自动推断：
 */
fun sumV2(a: Int, b: Int) = a + b

/**
 * 无返回值的函数(类似Java中的void)
 */
fun noReturn(a: Int, b: Int): Unit {

    println(a + b)
}

/**
 * 可变长参数函数
 */
fun vars(vararg v: Int) {
    for (i in v) {
        println(i)
    }
}

/**
 * 常量与变量都可以没有初始化值,但是在引用前必须初始化
 */
fun varVal() {
    val a: Int = 1
    val b = 1
    val c: Int/*常量与变量都可以没有初始化值,但是在引用前必须初始化*/
    c = 1

    var x = 5
    x += 1
}

/**
 * 字符串模板
 */
fun stringTemplate() {
    val a = 1
    val s1 = "a is $a"
    println(s1)

    val b = 2
    val s2 = "${s1.replace("is", "was")},but now is $a"
    println(s2)
}

/**
 *可null变量
 */
fun nullCheck() {

    val age: String? = "23"
    val ages: Int = age!!.toInt()
    val age1 = age?.toInt()
    val age2 = age?.toInt() ?: -1

    println("$age $ages $age1 $age2")
}

/**
 *可为 null 的函数
 */
fun parseInt(str: String): Int? {
    return str.toIntOrNull()
}

/**
 *
 */
fun printProduct(arg1: String, arg2: String) {
    val x = parseInt(arg1)
    val y = parseInt(arg2)

    if (x != null && y != null) {
        println(x * y)
    } else {
        println("$x $y is not a number")
    }
}

fun getStringLength(obj: Any): Int? {
    if (obj is String) return obj.length
    return null
}

fun getStringLengthV2(obj: Any): Int? {
    if (obj !is String) {
        return null
    }
    return obj.length
}

/**
 *区间
 */
fun range() {
    for (i in 1..4) {
        print("$i")
    }
    println()
    for (i in 4..1) {
        print("$i")
    }
    println()
    for (i in 1..4 step 2) {
        print(i)
    }
    println()
    for (i in 4 downTo 1) {
        print(i)
    }
    println()
    for (i in 1 until 4) {
        print(i)
    }
    println()
}

fun basicNumber() {
    val a = 1
    val b = 1.00
    val c = 1.00f
    val d = 1111111111111111111L
    val e = 0x10
    val f = 0b10
}

fun compare() {
    val a = 1000000
    println(a === a)

    val anotherA: Int? = a
    val againAnotherA: Int? = a

    println(anotherA == againAnotherA)
    println(anotherA === againAnotherA)
}

fun typeCast() {
    val b: Byte = 1
    //val c: Int = b /*Byte不能直接赋值给Int*/
    val d: Int = b.toInt()
}

fun move() {
    val a = 0b10
    println("左移 ${a.shl(1)}")
    println("右移 ${a.shr(1)}")
    println("无符号右移 ${a.inv().ushr(1)}")
    println("与 ${a.and(0)}")
    println("或 ${a.or(0)}")
    println("异或0 ${a.xor(0)}")
    println("异或1 ${a.xor(1)}")
    println("取反 ${a.inv()}")
}

fun array() {
    val a = arrayOf(1, 2, 3)
    val b = Array(3) { i -> i * 2 }

    println(a[2])
    println(b[2])
}

fun strFor() {
    val s = "HelloWorld"
    for (c in s) {
        print(c)
        print(" ")
    }
}

fun multiLineString() {
    val s = """
    |多行字符串
    |菜鸟教程
    |多行字符串
    |Runoob 
    """.trimIndent()
    println(s)
    println("$s length is ${s.length}")

    val p = """
        ${'$'}9.99
    """.trimIndent()
    println(p)
}

fun ifFunction(a: Int, b: Int) {
    var max = a
    if (a < b) {
        max = b
    }
    println(max)

    if (a > b) {
        max = a
    } else {
        max = b
    }
    println(max)

    max = if (a > b) a else b
    println(max)
}

fun ifRange(a: Int) {
    if (a in 1..9) {
        println("${a}在区间之内")
    } else {
        println("${a}不在区间之内")
    }
}

fun whenFunction(x: Int) {
    when (x) {
        1 -> println("x == 1")
        2 -> println("x == 2")
        else -> println("x is not 1 and 2")
    }

    when (x) {
        1, 2 -> println("x is $x")
        else -> println("x is otherwise")
    }

    val validNumbers = arrayOf(1, 52, 69, 999)
    when (x) {
        in 1..10 -> println("$x is in range")
        in validNumbers -> println("$x is valid")
        !in 20..50 -> println("$x is out range of")
        else -> println("this is nothing")
    }
}

fun hasPrefix(x: Any) = when (x) {
    is String -> x.startsWith("prefix")
    else -> false
}

fun whenFunction() {
    val items = setOf("apple", "banana", "kiwi")
    when {
        "orange" in items -> println("juicy")
        "apple" in items -> println("apple is fine too")
    }
}

fun forFunction() {
    val items = arrayOf("a", "b", "c", "d", "e", "f")
    for (i in items) {
        print(i)
        print(" ")
    }
    println()
    for (i in items.indices) {
        print(items[i])
        print(" ")
    }
    println()
    for ((i, v) in items.withIndex()) {
        print("$i $v")
        print(" ")
    }
}

fun doWhile() {
    var x = 5
    while (x > 0) {
        println(x--)
    }
    println("=========")
    var y = 5
    do {
        println(y--)
    } while (y > 0)
}

fun continueBreak() {
    for (i in 1..100) {
        if (i == 3) {
            continue
        }
        if (i > 5) {
            break
        }
        println(i)
    }
}

fun labelFunction() {
    for (i in 1..9) {
        for (j in 'a'..'z') {
            if (i > 1 && j > 'b') {
                break
            }
            println("$i $j")
        }
    }

    lable@ for (i in 1..9) {
        for (j in 'a'..'z') {
            if (i > 1 && j > 'b') {
                break@lable
            }
            println("$i $j")
        }
    }
}

fun foo() {
    val list = arrayOf(1, 2, 3, 4, 5)
    list.forEach label@{
        if (it > 3) {
            return@label
        }
        println("$it")
    }
    println(list)
}

class Runoob constructor(val name: String, val fatherName: String, age: Int) {

    init {
        print("$name $fatherName $age")
    }

    constructor(name: String, fatherName: String, age: Int, height: Float) : this(name, fatherName, age) {
        println("$height")
    }

    var lastName: String = "zhang"
        get() = field.uppercase()
        set(newName) {
            if (newName.isNullOrEmpty()) {
                return
            }
            field = newName
        }


    fun foo() {
        println("foo")
    }
}

open class FooClass {
    open fun check() {

    }
}

abstract class SonClass : FooClass() {
    abstract override fun check()
}

class Out {

    val age = 15
    val name = "zhangsan"

    class In {}

    inner class InnerClass {
        fun foo() = age
        fun innerTest() {
            val v = this@Out.name
            println("引用外部成员$v $this@Out")
        }
    }

    fun setInterface(face: TestInterface) {
        face.test()
    }
}

interface TestInterface {
    fun test()
}

open class Person(val name: String, val age: Int) {

    open fun sayHello() {
        println("你好")
    }
}

class Student(name: String, age: Int, val score: Float, val num: Int) : Person(name, age) {

    constructor() : this("null", 0, 90f, 0) {

    }

    override fun sayHello() {
        println("老师好")
    }
}

open class A {
    open fun f() {
        println("A")
    }
}

interface B {
    fun f() {
        println("B")
    }
}

class C : A(), B {
    override fun f() {
        super<A>.f()
        super<B>.f()
        println("C")
    }
}

open class D {
    open val count: Int = 0
}

class E(override val count: Int) : D() {}

interface F {
    val count: Int

    fun methodA() {
        println("A")
    }

    fun methodB()
}

class G(override val count: Int) : F {
    override fun methodB() {
        println("this is method B")
    }
}

class H(val name: String) {

}

fun H.print() {
    print("$name")
}

fun <T> MutableList<T>.swap(indexA: Int, indexB: Int) {
    val any = this[indexA]
    val any1 = this[indexB]
    this[indexA] = any1
    this[indexB] = any
}

open class FooMethodA

class FooMethodB : FooMethodA()

fun FooMethodA.foo() {
    println("FooMethodA's Foo() call")
}

fun FooMethodB.foo() {
    println("FooMethodB's Foo() call")
}

fun callFoo(call: FooMethodA) {
    call.foo()
}

class Mine {
    companion object {

    }
}

fun Mine.Companion.foo() {
    println("Companion extent mothod")
}

/**
 * 可以扩展get,不能扩展set
 */
val Mine.Companion.no: Int
    get() = 25


val FooMethodB.no: Int
    get() = 24

class C1 {
    fun selfFun() {
        println("c1 call self function")
    }
}

class D1 {
    fun selfFun() {
        println("call self function")
    }

    /**
     * 类内扩展只能类调用
     */
    fun C1.exFun() {
        println("call c1 extend function")
    }

    fun callCExfun(c1: C1) {
        c1.exFun()
        c1.sameFun()
    }

    fun C1.sameFun() {
        selfFun()
        this@D1.selfFun()
    }
}

data class PersonV1(val name: String, val age: Int)
data class PersonV2(var name: String, var age: Int)

sealed class Result {
    data class Success(val data: Any) : Result()
    data class Failed(val msg: String) : Result()
    object Exception : Result()
}


fun handleResult(res: Result) {
    when (res) {
        is Result.Success -> println(res.data)
        is Result.Failed -> println(res.msg)
        Result.Exception -> println("is exception")
    }
}

class Box<T>(val t: T) {

}

fun <T> copyWhenGreater(list: List<T>, base: T): List<String> where T : CharSequence, T : Comparable<T> {

    return list.filter { it > base }.map { it.toString() }
}

interface TestT<in E, out T> {
    fun map(e: E): T
}